﻿using System;
using System.Threading.Tasks;
using SaiLing.Domain;
using SaiLing.Domain.Specification;
using SaiLing.Exceptions;
using SaiLing.SingleSignOn.Application.Service.Interfaces.System;
using SaiLing.SingleSignOn.Domain.Entities.System;
using SaiLing.SingleSignOn.Domain.Interfaces.System;
using SaiLing.SingleSignOn.Domain.Specifications.System;
using System.Collections.Generic;
using SaiLing.Paging;
using SaiLing.SingleSignOn.Domain.Entities.DataTransferObject;
using System.Linq;

namespace SaiLing.SingleSignOn.Application.Service.Providers.System
{
    public class AccountService : BaseService<Account>, IAccountService
    {
       private   IAccountRepository AccountRepository { get; set; }
        public AccountService(IUnitOfWork unitOfWork, IAccountRepository repository) : base(unitOfWork, repository)
        {
            AccountRepository = repository;
        }

        public async Task<Account> SignIn(string userName, string password)
        {
            var user = await this.GetByCondition(new DirectSpecification<Account>(x => x.LoginName == userName && x.LogicRemove == false));
            if (user == null)
                throw new SaiLingException("该用户不存在.");
            var encodedPassword = password.EncryptPassword(user.PasswordSalt);
            var valid = encodedPassword == user.Password;
            if (!valid)
            {
                throw new SaiLingException("用户名或密码不正确.");
            };
            user.LastLoginDate = DateTime.UtcNow;
            Update(user, x => x.LastLoginDate);
            await UnitOfWork.SaveChangesAsync();
            return user;
        }

        public Task<IEnumerable<Account>> List(string name)
        {
            var spec = new AccountSpecification(name);
            return Task.FromResult(GetMany(spec));
        }

        public Task<PageData<Account>> PageList(int pageIndex, int pageSize, string name)
        {
            var spec = new AccountSpecification(name);
            return GetMany(spec).ToPageData(pageIndex, pageSize);
        }

        public Task Create(Account entity, LogUser user)
        {
            if (ExistsAsync(new DirectSpecification<Account>(x => x.LoginName == entity.LoginName)).Result)
                throw new SaiLingException("登录名重复");
            entity.PasswordSalt = StringExtensions.GenerateSalt();
            entity.Password = entity.Password.EncryptPassword(entity.PasswordSalt);
            Add(entity);
            return ServiceFactory.LogService.LogAsync("创建用户", $"创建了用户:{entity.LoginName}", user);

        }

        public Task Edit(Account entity, LogUser user)
        {
            if (ExistsAsync(new DirectSpecification<Account>(x => x.Id != entity.Id && x.LoginName == entity.LoginName)).Result)
                throw new SaiLingException("登录名重复");
           

            AccountRepository.Edit(entity);

            //Update(entity,
            //    x => x.Name,
            //    x => x.Email,
            //    x => x.IsAdministrator,
            //    x => x.IsAppAdministrator,
            //    x => x.IsLockedOut,
            //    x => x.LastLockoutDate,
            //    x => x.LastLoginDate,
            //    x => x.LastPasswordChangedDate,
            //    x => x.LoginName,
            //    x => x.Password,
            //    x => x.IsApproved);
            return ServiceFactory.LogService.LogAsync("修改用户", $"修改了用户:{entity.LoginName}", user);
        }

        public Task EditPassword(Account entity, LogUser user)
        {
            var et = GetByKey(entity.Id).Result;
            entity.Password = entity.Password.EncryptPassword(et.PasswordSalt);
            et.Password = entity.Password;


            Update(et,
                x => x.Password);
            return ServiceFactory.LogService.LogAsync("修改密码", $"修改了用户密码:{entity.LoginName}", user);
        }

        public Task EditLock(Account entity, LogUser user)
        {
            entity.IsLockedOut = false;
            entity.LastLockoutDate = DateTime.Now;
            Update(entity,
                x => x.IsLockedOut,
                x =>x.LastLockoutDate);
            return ServiceFactory.LogService.LogAsync("锁定用户", $"锁定用户:{entity.LoginName}", user);
        }

        public Task EditUnLock(Account entity, LogUser user)
        {
            entity.IsLockedOut = true;
            Update(entity,
                x => x.IsLockedOut);
            return ServiceFactory.LogService.LogAsync("解锁用户", $"解定用户:{entity.LoginName}", user);
        }

        public Task Delete(Account[] entityies, LogUser user)
        {
            var ids = entityies.Select(x => x.Id).ToList();
            LogicRemove(new DirectSpecification<Account>(x => ids.Contains(x.Id)));
            return ServiceFactory.LogService.LogAsync("删除用户", $"删除了:{entityies.Count()}条用户", user);
        }
    }
}
